﻿using System;
using Novell.Directory.Ldap;
using Mono.Security.X509;
using Mono.Security.Cryptography;
using Syscert = System.Security.Cryptography.X509Certificates;

namespace Alogient.Cameleon.Membership.Extension
{
    internal class Novell
    {
        public const int SslLdapPort = 636;

        protected static bool HowToProceed, Quit, RemoveFlag;
        protected static int BindCount;

        public static bool ValidateUser(string username, string password)
        {
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                return false;

            Items.ExtensionParameters extension = Services.GetActiveExtension();

            bool validated = false;

            HowToProceed = true;

            try
            {
                string ldapHost = extension.Param1;
                int ldapPort = Convert.ToInt32(extension.Param2);
                string loginDn = string.Format(extension.Param4, username);

                // Create Connection
                LdapConnection conn = new LdapConnection();
                conn.SecureSocketLayer = ldapPort == SslLdapPort;

                if (conn.SecureSocketLayer)
                {
                    conn.UserDefinedServerCertValidationDelegate += MySSLHandler;
                    HowToProceed = true;
                }

                if (HowToProceed)
                {
                    string[] loginDNs = loginDn.Split(';');
                    conn.Connect(ldapHost, ldapPort);

                    for (int i = 0; i < loginDNs.Length; i++)
                    {
                        try
                        {
                            conn.Bind(loginDNs[i], password);
                            validated = true;
                            break;
                        }
                        catch (Exception)
                        {
                            //
                        }
                    }
                }

                conn.Disconnect();

                Quit = false;
            }
            catch (Exception)
            {
                validated = false;
            }

            return validated;
        }

        // This is the Callback handler - after "Binding" this is called
        public static bool MySSLHandler(Syscert.X509Certificate certificate, int[] certificateErrors)
        {

            X509Store store;
            X509Stores stores = X509StoreManager.LocalMachine;
            store = stores.TrustedRoot;

            //Import the details of the certificate from the server.

            X509Certificate x509 = null;
            X509CertificateCollection coll = new X509CertificateCollection();
            byte[] data = certificate.GetRawCertData();
            if (data.Length != 0)
                x509 = new X509Certificate(data);

            HowToProceed = true;
            if (HowToProceed)
            {
                //Add the certificate to the store. This is \Documents and Settings\program data\.mono. . .
                if (x509 != null)
                    coll.Add(x509);
                store.Import(x509);
                if (BindCount == 1)
                    RemoveFlag = true;
            }

            if (HowToProceed == false)
            {
                //Remove the certificate added from the store.

                if (RemoveFlag && BindCount > 1)
                {
                    foreach (X509Certificate xt509 in store.Certificates)
                    {
                        if (x509 != null && CryptoConvert.ToHex(xt509.Hash) == CryptoConvert.ToHex(x509.Hash))
                        {
                            store.Remove(x509);
                        }
                    }
                }
                //Response.Write("SSL Bind Failed.");
            }

            return HowToProceed;
        }
    }
}
